/* Copyright 2001,2002,2003 NAH6
 * All Rights Reserved
 *
 * Parts Copyright DoD, Parts Copyright Starium
 *
 */
#include <fxpt.h>
#include <assert.h>

/***************************************************************************
 *
 *   FUNCTION NAME: fxpt_div
 *
 *   PURPOSE:
 *
 *     Divide a 32-bit numerator by a 32-bit denominator to the
 *     specified precison.  Result is 16-bits long.
 *
 *   INPUTS:
 *
 *     L_num
 *                     32-bit signed integer (fxpt_32) representing
 *                     the numerator of the fraction to be computed.
 *
 *     L_den
 *                     32-bit signed integer (fxpt_32) representing
 *                     the denominator of the fraction to be computed.
 *
 *     fr_bits
 *                     16-bit signed integer (fxpt_16) representing
 *                     the number of fractional bits desired in the
 *                     result.  This number must be in the range
 *                     0 <= fr_bits <= 15.
 *
 *   OUTPUTS:
 *
 *     none
 *
 *   RETURN VALUE:
 *
 *     L_frac
 *                     16-bit signed integer (fxpt_32) whose value
 *                     represents the value of num / den with fr_bits
 *                     on fractional value.
 *
 *   IMPLEMENTATION:
 *
 *     Convert L_num and L_den to positive values, noting the proper
 *     sign of the result.  Shift L_num left one bit at a time until
 *     either bit 30 is set or fr_bits of shifts have taken place.
 *     If fewer than fr_bits of shifts have taken place, shift L_den
 *     right until the total number of left shifts in L_num plus
 *     right shifts in L_den equals fr_bits.
 *
 *     If den != 0, compute num/den and store the result in L_frac.
 *     Adjust the sign of L_frac as necessary and return.  If den
 *     == 0, set L_frac to FX16_MAX and adjust the sign as necessary.
 *
 *   KEYWORDS: divide, fraction
 *
 *************************************************************************/

fxpt_32
fxpt_div32_org(fxpt_32 L_num, fxpt_32 L_den, int fr_bits);

#if 1
fxpt_32
fxpt_div32(fxpt_32 L_num, fxpt_32 L_den, int fr_bits)
{
	fxpt_64 res;

	if( L_den==0 )
	{
		if( L_num<0 )
			return FX32_MIN;
		else
			return FX32_MAX;
	}

	res= (((((fxpt_64)L_num)<< (fr_bits+1))/ L_den)+1)>>1;

	if( res>FX32_MAX )
		res= FX32_MAX;
	else if( res<FX32_MIN )
		res= FX32_MIN;

	return (fxpt_32)res;
}
#endif

#if 0
fxpt_32
fxpt_div32(fxpt_32 L_num, fxpt_32 L_den, int fr_bits)
{
  int sign = 1;
  fxpt_32 L_result;

  /* We need to work with a positive numerator.
   */
  if (L_num < 0) {
    L_num = -L_num;
    sign = -1;
  }


  /* Shift numerator left fr_bits times, or if that would
   * result in an overflow, then as far left as necessary to
   * set bit 30.  (NOTE:  Cast below is critical since hex
   * constants are treated as unsigned by default!)
   */
  if (((int32)0x80000000 >> fr_bits) & L_num) {

    do {
      L_num <<= 1;
      fr_bits--;
    } while ((L_num & 0x40000000) == 0);

    /*  Shift the denominator right the remaining number of times
     *  necessary to reach the specified precison.
     */
    L_den >>= fr_bits;
  }
  else {
    L_num <<= fr_bits;
  }


  if (L_den != 0) {
    /* Restore numerator's sign */
    L_num *= sign;
    L_result = L_num / L_den;
  }
  else {
    /* I'm not clear on why this isn't FX32_MAX, but I'll leave it. */
    L_result = FX16_MAX;
  }

  return L_result;
}
#endif
